import {
  Directive,
  HostListener,
  ElementRef,
  Renderer2,
  Input,
  Output,
  EventEmitter,
} from '@angular/core';
import { DragDropService, DragData } from '../directives.services';
import { take } from 'rxjs/operators';

@Directive({
  selector: '[dropTag]',
})
export class DropDirective {
  /*拖拽至目标元素时发射的事件*/
  @Output()
  dropped = new EventEmitter<DragData>();

  /*设定目标区域的标识*/
  @Input()
  dropTag: any;

  private data$;
  constructor(
    private el: ElementRef,
    private rd: Renderer2,
    private service: DragDropService
  ) {
    this.data$ = this.service.getDragData().pipe(take(1));
  }

  @HostListener('dragenter', ['$event'])
  onDragEnter(ev: Event) {
    //判断drag元素是不是指令应用的元素发起的
    if (this.el.nativeElement === ev.target) {
      this.data$.subscribe((dragData) => {
        if (dragData && this.dropTag == dragData.tag) {
        }
      });
    }
  }

  //dragover允许进行data transfer的一些特效
  @HostListener('dragover', ['$event'])
  onDragOver(ev: Event) {
    //需要支持多级拖拽，所以要防止事件冒泡
    ev.preventDefault();
    ev.stopPropagation();
    if (this.el.nativeElement === ev.target) {
      this.data$.subscribe((dragData) => {
        if (dragData && this.dropTag == dragData.tag) {
          this.rd.setProperty(ev, 'dataTransfer.effectAllowed', 'all');
          this.rd.setProperty(ev, 'dataTransfer.fropEffect', 'move');
        } else {
          this.rd.setProperty(ev, 'dataTransfer.effectAllowed', 'none');
          this.rd.setProperty(ev, 'dataTransfer.dropEffect', 'none');
        }
      });
    }
  }

  @HostListener('dragleave', ['$event'])
  onDragLeave(ev: Event) {
    ev.preventDefault();
    ev.stopPropagation();
    if (this.el.nativeElement === ev.target) {
      this.data$.subscribe((dragData) => {
        if (dragData && this.dropTag == dragData.tag) {
        }
      });
    }
  }

  @HostListener('drop', ['$event'])
  onDrop(ev: Event) {
    ev.preventDefault();
    ev.stopPropagation();
    if (this.el.nativeElement === ev.target) {
      this.data$.subscribe((dragData) => {
        if (dragData && this.dropTag == dragData.tag) {
          this.dropped.emit(dragData); //drop的时候把dragData发射出去
          this.service.clearDragData(); //drop的时候把data clear掉，否则会影响下一次拖拽
        }
      });
    }
  }
}
